package com.apes.oap.security;

import com.apes.oap.RopException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

/**
 * <pre>
 * 基于文件管理的应用密钥
 * </pre>
 *
 * @version 1.0
 */
public class FileBaseAppSecretManager implements AppSecretManager {
    protected final Log logger = LogFactory.getLog(this.getClass());

    private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";

    private static final String DEFAULT_NAMES = "rop.appSecret.properties";

    private Properties properties;

    public String getSecret(String appKey) {
        if (properties == null) {
            try {
                Resource resource = new Loader().load();
                properties = PropertiesLoaderUtils.loadProperties(resource);
            } catch (IOException e) {
                throw new RopException("在类路径下找不到rop.appSecret.properties的应用密钥的属性文件", e);
            }
        }
        String secret = properties.getProperty(appKey);

        if (secret == null) {
            logger.error("不存在应用键为{0}的密钥,请检查应用密钥的配置文件。" + appKey);
        }
        return secret;
    }

    public boolean isValidAppKey(String appKey) {
        return getSecret(appKey) != null;
    }

    /**
     * Loads candidate property sources and configures the active profiles.
     */
    private class Loader {
        private final ResourceLoader resourceLoader;

        Loader() {
            this.resourceLoader = new DefaultResourceLoader();
        }

        public Resource load() {
            for (String location : getSearchLocations()) {
                for (String name : getSearchNames()) {
                    Resource resource = this.resourceLoader.getResource(location + name);
                    if (resource != null && resource.exists()) {
                        return resource;
                    }
                }
            }
            return resourceLoader.getResource(DEFAULT_NAMES);
        }

        private Set<String> getSearchLocations() {
            Set<String> locations = new LinkedHashSet<String>();
            locations.addAll(asResolvedSet(DEFAULT_SEARCH_LOCATIONS));
            return locations;
        }

        private Set<String> getSearchNames() {
            return asResolvedSet(DEFAULT_NAMES);
        }

        private Set<String> asResolvedSet(String fallback) {
            List<String> list = Arrays.asList(StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(fallback)));
            Collections.reverse(list);
            return new LinkedHashSet<>(list);
        }

    }

}
